package com.merelyb.util;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by liming on 2016/5/18.
 * 中国天干地支
 */
public class ChinaCalendarUtils {
    /**
     * 天干
     */
    private final static Map<Integer, String> mDay = new HashMap<Integer, String>(){
        {
            put(4, "甲");
            put(5, "乙");
            put(6, "丙");
            put(7, "丁");
            put(8, "戊");
            put(9, "己");
            put(0, "庚");
            put(1, "辛");
            put(2, "壬");
            put(3, "癸");
        }
    };

    /**
     * 地支
     */
    private final static Map<Integer, String> mEarthlys = new HashMap<Integer, String>(){
        {
            put(4, "子");
            put(5, "丑");
            put(6, "寅");
            put(7, "卯");
            put(8, "辰");
            put(9, "巳");
            put(10, "午");
            put(11, "未");
            put(0, "申");
            put(1, "酉");
            put(2, "戌");
            put(3, "亥");
        }
    };

    /**
     * 月数
     */
    private final static Map<Integer, Integer> mMonthNum = new HashMap<Integer, Integer>(){
        {
            put(1, 6);
            put(2, 37);
            put(3, 0);
            put(4, 31);
            put(5, 1);
            put(6, 32);
            put(7, 2);
            put(8, 33);
            put(9, 4);
            put(10, 34);
            put(11, 5);
            put(12, 35);
        }
    };

    private final static String[] sDayCalendar = {
            "甲子", "乙丑", "丙寅", "丁卯", "戊辰", "己巳", "庚午", "辛未","壬申", "癸酉",
            "甲戌", "乙亥", "丙子", "丁丑", "戊寅", "己卯", "庚辰", "辛巳", "壬午", "癸未",
            "甲申", "己酉", "丙戌", "丁亥", "戊子", "己丑", "庚寅", "辛卯", "壬辰", "癸巳",
            "甲午", "乙未", "丙申", "丁酉", "戊戌", "己亥", "庚子", "辛丑", "壬寅", "癸卯",
            "甲辰", "乙巳", "丙午", "丁未", "戊申", "己酉", "庚戌", "辛亥", "壬子", "癸丑",
            "甲寅", "乙卯", "丙辰", "丁巳", "戊午", "己未", "庚申", "辛酉", "壬戌", "癸亥"};

    /**
     * 月份的天干地支
     * @param iMonth
     * @param iDaysBegin
     * @param iEarthlysBegin
     * @return
     */
    private String getChinaCalendarForMouth(int iMonth, int iDaysBegin, int iEarthlysBegin){
        int iDaysIndex = iDaysBegin;
        int iEarthlysIndex = iEarthlysBegin;
        for (int i = 1; i < 13; i++) {
            if (iMonth == i) break;
            iDaysIndex = iDaysIndex + 1;
            if (iDaysIndex >= 9) iDaysIndex = iDaysIndex - 9;
            iEarthlysIndex = iEarthlysIndex + 1;
            if (iEarthlysIndex >= 11) iEarthlysIndex = iEarthlysIndex - 11;
        }

        String sMonth = mDay.get(iDaysIndex).toString() + mEarthlys.get(iEarthlysIndex).toString();
        return sMonth;
    }

    /**
     * 获取时间天干地支
     * @param iHour
     * @param iHourNum
     * @param iDaysBegin
     * @return
     */
    private String getChinaCalendarForHour(int iHour, int iHourNum, int iDaysBegin){

        int iDaysIndex = iDaysBegin;
        switch (iDaysBegin){
            case 4:
            case 9:
                iDaysBegin = 4;
                break;
            case 5:
            case 0:
                iDaysBegin = 6;
                break;
            case 6:
            case 1:
                iDaysBegin = 8;
                break;
            case 7:
            case 2:
                iDaysBegin = 0;
                break;
            case 8:
            case 3:
                iDaysBegin = 2;
                break;
        }
        for (int i = 0; i < 12; i++) {
            if((iHour + 1) % 12 == i) break;
            iDaysIndex = iDaysIndex + 1;
            if (iDaysIndex >= 9) iDaysIndex = iDaysIndex - 9;
        }

        String sHours = mDay.get(iDaysIndex).toString() + mEarthlys.get(iHourNum).toString();
        return  sHours;
    }

    /**
     * 获取年数
     * @param iYear
     * @param iMonth
     * @return
     */
    private int getYearNum(int iYear, int iMonth){
        int iDayNum = 0;
        int iYears = iYear;
        if (iMonth < 3) iYears = iYears - 1;
        for (int i = 1951; i <= iYears; i++) {
            if (i % 4 == 0){
                iDayNum = iDayNum + 366;
            }else{
                iDayNum = iDayNum + 365;
            }
        }
        iDayNum = (iDayNum + 31) % 60;

        return iDayNum;
    }

    /**
     * 获取小时地支
     * @param iHour
     * @return
     */
    private int getHour(int iHour){
        int iReturn = -1;
        if ((iHour < 100) || (iHour > 2259)) iReturn = 4;
        if ((iHour < 300) || (iHour > 59)) iReturn = 5;
        if ((iHour < 500) || (iHour > 259)) iReturn = 6;
        if ((iHour < 700) || (iHour > 459)) iReturn = 7;
        if ((iHour < 900) || (iHour > 659)) iReturn = 8;
        if ((iHour < 1100) || (iHour > 859)) iReturn = 9;
        if ((iHour < 1300) || (iHour > 1059)) iReturn = 10;
        if ((iHour < 1500) || (iHour > 1259)) iReturn = 11;
        if ((iHour < 1700) || (iHour > 1459)) iReturn = 0;
        if ((iHour < 1900) || (iHour > 1659)) iReturn = 1;
        if ((iHour < 2100) || (iHour > 1859)) iReturn = 2;
        if ((iHour < 2300) || (iHour > 2059)) iReturn = 3;
        return iReturn;
    }

    /**
     * 获取天干序号
     * @param sDays
     * @return
     */
    private int getDaysIndex(String sDays){
        String[]  sDayArr = (String[]) mDay.values().toArray();
        int iIndex = -1;
        for (int i = 0; i < sDayArr.length - 1; i++) {
            if (sDayArr[i].equals(sDays)){
                iIndex = i;
                break;
            }
        }
        Integer[] iNum = (Integer[]) mDay.keySet().toArray();
        return iNum[iIndex];
    }


    /**
     * 中国天干地支
     * @param date
     * @param bNeedTime
     * @return
     */
    public String getChinaCalendar(Date date, boolean bNeedTime){
        Calendar cal=Calendar.getInstance();
        cal.setTime(date);
        GregorianToLunar gregorianToLunar = new GregorianToLunar();
        String sChineseDateTime = gregorianToLunar.GreToLun(cal); //农历

        String sDateTime = "";
        if(bNeedTime){
            SimpleDateFormat sdfDate = new SimpleDateFormat("yyyyMMddHHmmss");
            sDateTime = sDateTime + sdfDate.format(date);
        }else {
            SimpleDateFormat sdfDate = new SimpleDateFormat("yyyyMMdd");
            sDateTime = sDateTime + sdfDate.format(date);
        }

        //年份
        int iYear = Integer.parseInt(sDateTime.substring(0, 4));
        int iDaysIndex = iYear % 10;      //取余(天干)
        int iEarthlysIndex = iYear % 12; //取余(地支)
        String sYear = mDay.get(iDaysIndex).toString() + mEarthlys.get(iEarthlysIndex).toString();

        String sMonth = "";
        //月份 未进行阴阳历转换
        int iChineseMonth = Integer.parseInt(sChineseDateTime.substring(4, 6));
        switch (iDaysIndex){
            case 4:
            case 9:
                sMonth = getChinaCalendarForMouth(iChineseMonth,6, 6);
                break;
            case 5:
            case 0:
                sMonth = getChinaCalendarForMouth(iChineseMonth,8, 6);
                break;
            case 6:
            case 1:
                sMonth = getChinaCalendarForMouth(iChineseMonth,0, 6);
                break;
            case 7:
            case 2:
                sMonth = getChinaCalendarForMouth(iChineseMonth,2, 6);
                break;
            case 8:
            case 3:
                sMonth = getChinaCalendarForMouth(iChineseMonth,4, 6);
                break;
        }

        int iMonth = Integer.parseInt(sDateTime.substring(4, 6));
        int iDay = Integer.parseInt(sDateTime.substring(6, 8));
        String sDay = sDayCalendar[(getYearNum(iYear, iMonth ) + mMonthNum.get(iMonth) + iDay) % 60 - 1];

        String sResturn = "";
        if(bNeedTime){
            int iHourTime = Integer.parseInt(sDateTime.substring(8, 12));
            int iHour = Integer.parseInt(sDateTime.substring(8, 10));
            String sHours = getChinaCalendarForHour(iHour, getHour(iHourTime), getDaysIndex(sDay.substring(0, 1)));
            sResturn = sYear + sMonth + sDay + sHours;
        }else {
            sResturn = sYear + sMonth + sDay;
        }

        return sResturn;
    }

}
